package com.wujie.mall.domain.order.builder;

import com.wujie.mall.domain.order.*;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * 订单构建器 - 建造者模式实现
 * 
 * 设计模式：Builder Pattern（建造者模式）
 * 应用场景：构建复杂的订单对象，支持链式调用和灵活配置
 * 
 * 核心特点：
 * 1. 链式调用，提供流畅的API
 * 2. 分步构建，可以灵活控制构建过程
 * 3. 参数验证，确保构建的对象符合业务规则
 * 4. 默认值设置，简化常见场景的使用
 * 5. 构建过程封装，隐藏复杂的创建逻辑
 * 
 * @author wujie
 * @since 2024-08-26
 */
@Slf4j
public class OrderBuilder {

    /**
     * 正在构建的订单对象
     */
    private Order order;

    /**
     * 订单项列表
     */
    private List<OrderItem> items;

    /**
     * 是否自动生成订单号
     */
    private boolean autoGenerateOrderNo = true;

    /**
     * 是否自动计算金额
     */
    private boolean autoCalculateAmount = true;

    /**
     * 是否验证构建结果
     */
    private boolean validateResult = true;

    /**
     * 私有构造函数，通过静态方法创建
     */
    private OrderBuilder() {
        this.order = new Order();
        this.items = new ArrayList<>();
        this.order.setCreatedAt(LocalDateTime.now());
        this.order.setUpdatedAt(LocalDateTime.now());
        this.order.setStatus(OrderStatus.PENDING_PAYMENT);
        log.debug("订单构建器初始化完成");
    }

    /**
     * 创建订单构建器实例
     * @return 订单构建器
     */
    public static OrderBuilder newOrder() {
        return new OrderBuilder();
    }

    /**
     * 基于现有订单创建构建器（用于订单修改）
     * @param existingOrder 现有订单
     * @return 订单构建器
     */
    public static OrderBuilder fromOrder(Order existingOrder) {
        OrderBuilder builder = new OrderBuilder();
        builder.order = Order.builder()
                .id(existingOrder.getId())
                .orderNo(existingOrder.getOrderNo())
                .userId(existingOrder.getUserId())
                .status(existingOrder.getStatus())
                .totalAmount(existingOrder.getTotalAmount())
                .payAmount(existingOrder.getPayAmount())
                .freight(existingOrder.getFreight())
                .discountAmount(existingOrder.getDiscountAmount())
                .shippingAddress(existingOrder.getShippingAddress())
                .remark(existingOrder.getRemark())
                .paymentMethod(existingOrder.getPaymentMethod())
                .paymentTime(existingOrder.getPaymentTime())
                .deliveryTime(existingOrder.getDeliveryTime())
                .completeTime(existingOrder.getCompleteTime())
                .cancelTime(existingOrder.getCancelTime())
                .createdAt(existingOrder.getCreatedAt())
                .updatedAt(LocalDateTime.now())
                .build();
        
        if (existingOrder.getItems() != null) {
            builder.items = new ArrayList<>(existingOrder.getItems());
        }
        
        builder.autoGenerateOrderNo = false; // 已有订单号，不自动生成
        log.debug("基于现有订单创建构建器，订单号: {}", existingOrder.getOrderNo());
        return builder;
    }

    /**
     * 设置订单号
     * @param orderNo 订单号
     * @return 构建器实例
     */
    public OrderBuilder orderNo(String orderNo) {
        this.order.setOrderNo(orderNo);
        this.autoGenerateOrderNo = false;
        log.debug("设置订单号: {}", orderNo);
        return this;
    }

    /**
     * 设置用户ID
     * @param userId 用户ID
     * @return 构建器实例
     */
    public OrderBuilder userId(Long userId) {
        this.order.setUserId(userId);
        log.debug("设置用户ID: {}", userId);
        return this;
    }

    /**
     * 设置订单状态
     * @param status 订单状态
     * @return 构建器实例
     */
    public OrderBuilder status(OrderStatus status) {
        this.order.setStatus(status);
        log.debug("设置订单状态: {}", status.getName());
        return this;
    }

    /**
     * 添加订单项
     * @param productId 商品ID
     * @param skuId SKU ID
     * @param productName 商品名称
     * @param unitPrice 单价
     * @param quantity 数量
     * @return 构建器实例
     */
    public OrderBuilder addItem(Long productId, Long skuId, String productName, BigDecimal unitPrice, Integer quantity) {
        OrderItem item = OrderItem.builder()
                .productId(productId)
                .skuId(skuId)
                .productName(productName)
                .unitPrice(unitPrice)
                .quantity(quantity)
                .build();
        item.calculateTotalPrice();
        this.items.add(item);
        log.debug("添加订单项: {} x{}", productName, quantity);
        return this;
    }

    /**
     * 添加订单项（完整版本）
     * @param item 订单项
     * @return 构建器实例
     */
    public OrderBuilder addItem(OrderItem item) {
        if (item != null) {
            item.calculateTotalPrice();
            this.items.add(item);
            log.debug("添加订单项: {} x{}", item.getProductName(), item.getQuantity());
        }
        return this;
    }

    /**
     * 批量添加订单项
     * @param items 订单项列表
     * @return 构建器实例
     */
    public OrderBuilder addItems(List<OrderItem> items) {
        if (items != null) {
            for (OrderItem item : items) {
                addItem(item);
            }
        }
        return this;
    }

    /**
     * 移除订单项
     * @param productId 商品ID
     * @param skuId SKU ID
     * @return 构建器实例
     */
    public OrderBuilder removeItem(Long productId, Long skuId) {
        this.items.removeIf(item -> 
            item.getProductId().equals(productId) && item.getSkuId().equals(skuId));
        log.debug("移除订单项: productId={}, skuId={}", productId, skuId);
        return this;
    }

    /**
     * 清空所有订单项
     * @return 构建器实例
     */
    public OrderBuilder clearItems() {
        this.items.clear();
        log.debug("清空所有订单项");
        return this;
    }

    /**
     * 设置收货地址
     * @param address 收货地址
     * @return 构建器实例
     */
    public OrderBuilder shippingAddress(ShippingAddress address) {
        this.order.setShippingAddress(address);
        log.debug("设置收货地址: {}", address != null ? address.getFormattedInfo() : "null");
        return this;
    }

    /**
     * 设置收货地址（简化版本）
     * @param receiver 收货人
     * @param phone 电话
     * @param province 省份
     * @param city 城市
     * @param district 区县
     * @param detail 详细地址
     * @return 构建器实例
     */
    public OrderBuilder shippingAddress(String receiver, String phone, String province, 
                                      String city, String district, String detail) {
        ShippingAddress address = ShippingAddress.builder()
                .receiver(receiver)
                .phone(phone)
                .province(province)
                .city(city)
                .district(district)
                .detail(detail)
                .build();
        return shippingAddress(address);
    }

    /**
     * 设置运费
     * @param freight 运费
     * @return 构建器实例
     */
    public OrderBuilder freight(BigDecimal freight) {
        this.order.setFreight(freight);
        log.debug("设置运费: {}", freight);
        return this;
    }

    /**
     * 设置优惠金额
     * @param discountAmount 优惠金额
     * @return 构建器实例
     */
    public OrderBuilder discountAmount(BigDecimal discountAmount) {
        this.order.setDiscountAmount(discountAmount);
        log.debug("设置优惠金额: {}", discountAmount);
        return this;
    }

    /**
     * 设置订单备注
     * @param remark 备注
     * @return 构建器实例
     */
    public OrderBuilder remark(String remark) {
        this.order.setRemark(remark);
        log.debug("设置订单备注: {}", remark);
        return this;
    }

    /**
     * 设置支付方式
     * @param paymentMethod 支付方式
     * @return 构建器实例
     */
    public OrderBuilder paymentMethod(String paymentMethod) {
        this.order.setPaymentMethod(paymentMethod);
        log.debug("设置支付方式: {}", paymentMethod);
        return this;
    }

    /**
     * 禁用自动生成订单号
     * @return 构建器实例
     */
    public OrderBuilder disableAutoGenerateOrderNo() {
        this.autoGenerateOrderNo = false;
        return this;
    }

    /**
     * 禁用自动计算金额
     * @return 构建器实例
     */
    public OrderBuilder disableAutoCalculateAmount() {
        this.autoCalculateAmount = false;
        return this;
    }

    /**
     * 禁用结果验证
     * @return 构建器实例
     */
    public OrderBuilder disableValidation() {
        this.validateResult = false;
        return this;
    }

    /**
     * 手动设置总金额（当禁用自动计算时使用）
     * @param totalAmount 总金额
     * @return 构建器实例
     */
    public OrderBuilder totalAmount(BigDecimal totalAmount) {
        this.order.setTotalAmount(totalAmount);
        log.debug("手动设置总金额: {}", totalAmount);
        return this;
    }

    /**
     * 手动设置实付金额（当禁用自动计算时使用）
     * @param payAmount 实付金额
     * @return 构建器实例
     */
    public OrderBuilder payAmount(BigDecimal payAmount) {
        this.order.setPayAmount(payAmount);
        log.debug("手动设置实付金额: {}", payAmount);
        return this;
    }

    /**
     * 构建订单对象
     * @return 构建完成的订单
     * @throws IllegalStateException 构建失败时抛出
     */
    public Order build() {
        log.debug("开始构建订单");

        try {
            // 1. 自动生成订单号
            if (autoGenerateOrderNo && (order.getOrderNo() == null || order.getOrderNo().trim().isEmpty())) {
                order.setOrderNo(generateOrderNo());
                log.debug("自动生成订单号: {}", order.getOrderNo());
            }

            // 2. 设置订单项
            order.setItems(new ArrayList<>(items));

            // 3. 自动计算金额
            if (autoCalculateAmount) {
                calculateAmounts();
                log.debug("自动计算金额完成，总金额: {}, 实付金额: {}", order.getTotalAmount(), order.getPayAmount());
            }

            // 4. 设置默认值
            setDefaultValues();

            // 5. 验证构建结果
            if (validateResult) {
                order.validate();
                log.debug("订单验证通过");
            }

            log.info("订单构建成功，订单号: {}, 订单项数: {}, 总金额: {}", 
                    order.getOrderNo(), order.getItemCount(), order.getTotalAmount());

            return order;

        } catch (Exception e) {
            log.error("订单构建失败: {}", e.getMessage(), e);
            throw new IllegalStateException("订单构建失败: " + e.getMessage(), e);
        }
    }

    /**
     * 生成订单号
     * @return 订单号
     */
    private String generateOrderNo() {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 8).toUpperCase();
        return "ORD" + timestamp + uuid;
    }

    /**
     * 计算订单金额
     */
    private void calculateAmounts() {
        // 计算商品总金额
        BigDecimal itemsTotal = items.stream()
                .map(OrderItem::getTotalPrice)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        order.setTotalAmount(itemsTotal);

        // 计算实付金额 = 商品总金额 + 运费 - 优惠金额
        BigDecimal freight = order.getFreight() != null ? order.getFreight() : BigDecimal.ZERO;
        BigDecimal discount = order.getDiscountAmount() != null ? order.getDiscountAmount() : BigDecimal.ZERO;
        
        BigDecimal payAmount = itemsTotal.add(freight).subtract(discount);
        order.setPayAmount(payAmount);
    }

    /**
     * 设置默认值
     */
    private void setDefaultValues() {
        if (order.getFreight() == null) {
            order.setFreight(BigDecimal.ZERO);
        }

        if (order.getDiscountAmount() == null) {
            order.setDiscountAmount(BigDecimal.ZERO);
        }

        if (order.getCreatedAt() == null) {
            order.setCreatedAt(LocalDateTime.now());
        }

        order.setUpdatedAt(LocalDateTime.now());
    }

    /**
     * 获取当前构建状态信息
     * @return 构建状态信息
     */
    public String getBuildStatus() {
        return String.format("OrderBuilder{订单号=%s, 用户ID=%s, 订单项数=%d, 自动生成订单号=%s, 自动计算金额=%s, 验证结果=%s}", 
                           order.getOrderNo(), 
                           order.getUserId(), 
                           items.size(),
                           autoGenerateOrderNo,
                           autoCalculateAmount,
                           validateResult);
    }

    @Override
    public String toString() {
        return getBuildStatus();
    }
}